﻿Imports System.IO
Imports Microsoft.SharePoint.Administration

Public Class Logger
    Implements IDisposable


#Region "Properties"
    Private _open As Boolean
    Public ReadOnly Property Open As Boolean
        Get
            Return _open
        End Get
    End Property

    Private _level As LogLevel
    Public Property LogLevel As LogLevel
        Get
            Return _level
        End Get
        Set(ByVal value As LogLevel)
            _level = value
        End Set
    End Property

    Private _web As SPWeb
    Public ReadOnly Property Web As SPWeb
        Get
            Return _web
        End Get
    End Property

    Private _HistoryList As SPList
    Private ReadOnly Property HistoryList As SPList
        Get
            If _historyList Is Nothing Then
                _HistoryList = Me.Web.Lists.TryGetList(ImportDataTimerJob.HISTORY_LIST_TITLE)
            End If
            Return _historyList
        End Get
    End Property

    Private _id As String
    Public ReadOnly Property Id As String
        Get
            Return _id
        End Get
    End Property

    Private _retention As Integer
    Private _startClock As DateTime
    Private _JobName As String

#End Region

    Public Sub New(ByVal web As SPWeb, ByVal jobName As String, ByVal historyLevel As LogLevel, ByVal retention As Integer)
        Me._open = True
        Me._web = web
        Me._JobName = jobName
        Me._level = historyLevel
        Me._retention = retention
        Me._id = Guid.NewGuid.ToString


        'Me.AddHistory(ImportDataTimer.LogLevel.Information, "Starting job at " + DateTime.Now.ToString)
    End Sub




    Public Sub Close(ByVal message As String)
        'purge logs
        Me.PurgeLogs()

        'close history
        Me.AddHistory(ImportDataTimer.LogLevel.Information, message)

        Me._open = False
    End Sub


    Public Sub AddHistory(ByVal level As LogLevel, ByVal message As String)
        If level <= Me._level Then
            If String.IsNullOrEmpty(message) Then
                Return
            End If

            Try
                Dim itemHistory As SPListItem = Me.HistoryList.AddItem()
                itemHistory(SPBuiltInFieldId.Title) = Me._JobName
                itemHistory("Log Level") = level.ToString
                itemHistory("Message") = message
                itemHistory("Result Id") = Me._id

                Dim value As New SPFieldUrlValue
                value.Url = String.Format("{0}/lists/{1}/", Me.HistoryList.ParentWeb.Url, ImportDataTimerJob.SETTINGS_LIST_TITLE)
                value.Description = "Settings List"
                itemHistory("Parent Result") = value

                Me.HistoryList.ParentWeb.AllowUnsafeUpdates = True
                itemHistory.Update()
                Me.HistoryList.ParentWeb.AllowUnsafeUpdates = False

            Catch ex As Exception
                logTraceInfo(String.Format("ex, JobName={0}", Me._JobName))
                logTraceInfo(String.Format("ex.Message={0}", ex.Message))
                logTraceInfo(String.Format("ex.StackTrace={0}", ex.StackTrace))
            End Try
        End If
    End Sub


    Public Shared Sub logTraceInfo(ByVal strMessage As String)
        If String.IsNullOrEmpty(strMessage) Then
            Return
        End If

        Dim diagSvc As SPDiagnosticsService = SPDiagnosticsService.Local
        diagSvc.WriteTrace(0, New SPDiagnosticsCategory(ImportDataTimerJob.JOB_NAME, TraceSeverity.Monitorable, EventSeverity.[Error]), TraceSeverity.Monitorable, "{0}", New Object() {strMessage})

    End Sub


#Region "IDisposable Support"
    Private disposedValue As Boolean

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing And Me._open Then
                Me.AddHistory(ImportDataTimer.LogLevel.Error, "Logger failed to close properly.")
                Me.Close("")
            End If
            _JobName = Nothing
            _HistoryList = Nothing
            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

#Region "Purge Methods"

    Private Sub PurgeLogs()
        'log.AddHistory(LogLevel.Verbose, String.Format("Purging logs older than {0} days.", settingItem.Retention))
        Dim query As New SPQuery
        query.Query = String.Format("<Where><And><Lt><FieldRef Name='Created' /><Value Type='DateTime'><Today OffsetDays='{0}'/></Value></Lt><Eq><FieldRef Name='Title' /><Value Type='Text'>{1}</Value></Eq></And></Where>", Me._retention * -1, Me._JobName)
        'query.Query = String.Format("<Where><Lt><FieldRef Name='Created' /><Value Type='DateTime'><Today OffsetDays='{0}'/></Value></Lt></Where>", Me._retention * -1, Me._JobName)

        'query.Query = String.Format("<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>{0}</Value></Eq></Where>", Me._JobName)
        Dim collection As SPListItemCollection = HistoryList.GetItems(query)
        Me.AddHistory(ImportDataTimer.LogLevel.Verbose, String.Format("Executed query: {0}", query.Query.ToString))
        Me.AddHistory(LogLevel.Verbose, "Removing " + collection.Count.ToString + " records from the " + HistoryList.Title + " list per retention setting.")

        Try
            Dim batch As String = BuildBatchDeleteCommand(_HistoryList, collection)
            _HistoryList.ParentWeb.AllowUnsafeUpdates = True
            _HistoryList.ParentWeb.ProcessBatchData(batch)
            '_HistoryList.Update()
            _HistoryList.ParentWeb.AllowUnsafeUpdates = False
            Me.AddHistory(LogLevel.Information, "Removed " + collection.Count.ToString + " records from the " + HistoryList.Title + " list per retention setting.")
        Catch ex As Exception
            Me.AddHistory(LogLevel.Warning, "Failed to remove history records.")
        End Try



    End Sub

    Private Function BuildBatchDeleteCommand(ByVal list As SPList, ByVal coll As SPListItemCollection) As [String]
        Dim sbDelete As New Text.StringBuilder()
        sbDelete.Append("<?xml version=""1.0"" encoding=""UTF-8""?><Batch>")

        Me.AddHistory(LogLevel.Verbose, "Creating batch delete command.  " + sbDelete.ToString)

        For Each item As SPListItem In coll
           Dim cmd As String = String.Format("<Method><SetList Scope=""Request"">{0}</SetList><SetVar Name=""ID"">{1}</SetVar><SetVar Name=""Cmd"">Delete</SetVar></Method>", list.ID, item.ID.ToString)
            sbDelete.Append(cmd)
        Next
        sbDelete.Append("</Batch>")
        Me.AddHistory(LogLevel.Information, "Created batch delete command.")
        Me.AddHistory(ImportDataTimer.LogLevel.VerboseDebug, sbDelete.ToString)
        Return sbDelete.ToString()
    End Function

#End Region

End Class
